// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

// ************************************************************************* //
//  File: avtDecimateFilter.C
// ************************************************************************* //

#include <avtDecimateFilter.h>

#include <vtkDecimatePro.h>
#include <vtkPolyData.h>
#include <vtkTriangleFilter.h>

#include <avtCallback.h>


// ****************************************************************************
//  Method: avtDecimateFilter constructor
//
//  Programmer: childs -- generated by xml2info
//  Creation:   Sun Aug 11 08:02:03 PDT 2002
//
// ****************************************************************************

avtDecimateFilter::avtDecimateFilter()
{
    haveIssuedWarning = false;
}


// ****************************************************************************
//  Method: avtDecimateFilter destructor
//
//  Programmer: childs -- generated by xml2info
//  Creation:   Sun Aug 11 08:02:03 PDT 2002
//
//  Modifications:
//
// ****************************************************************************

avtDecimateFilter::~avtDecimateFilter()
{
}


// ****************************************************************************
//  Method:  avtDecimateFilter::Create
//
//  Programmer: childs -- generated by xml2info
//  Creation:   Sun Aug 11 08:02:03 PDT 2002
//
// ****************************************************************************

avtFilter *
avtDecimateFilter::Create()
{
    return new avtDecimateFilter();
}


// ****************************************************************************
//  Method:      avtDecimateFilter::SetAtts
//
//  Purpose:
//      Sets the state of the filter based on the attribute object.
//
//  Arguments:
//      a        The attributes to use.
//
//  Programmer: childs -- generated by xml2info
//  Creation:   Sun Aug 11 08:02:03 PDT 2002
//
// ****************************************************************************

void
avtDecimateFilter::SetAtts(const AttributeGroup *a)
{
    atts = *(const DecimateAttributes*)a;
}


// ****************************************************************************
//  Method: avtDecimateFilter::Equivalent
//
//  Purpose:
//      Returns true if creating a new avtDecimateFilter with the given
//      parameters would result in an equivalent avtDecimateFilter.
//
//  Programmer: childs -- generated by xml2info
//  Creation:   Sun Aug 11 08:02:03 PDT 2002
//
// ****************************************************************************

bool
avtDecimateFilter::Equivalent(const AttributeGroup *a)
{
    return (atts == *(DecimateAttributes*)a);
}


// ****************************************************************************
//  Method: avtDecimateFilter::ExecuteData
//
//  Purpose:
//      Sends the specified input and output through the Decimate filter.
//
//  Arguments:
//      in_dr      The input data representation.
//
//  Returns:       The output data representation.
//
//  Programmer: childs -- generated by xml2info
//  Creation:   Sun Aug 11 08:02:03 PDT 2002
//
//  Modifications:
//
//    Hank Childs, Fri Sep  6 07:55:49 PDT 2002
//    Triangulate all of the surfaces before decimating (the filter crashes
//    otherwise).
//
//    Eric Brugger, Wed Jul 23 11:55:07 PDT 2014
//    Modified the class to work with avtDataRepresentation.
//
// ****************************************************************************

avtDataRepresentation *
avtDecimateFilter::ExecuteData(avtDataRepresentation *in_dr)
{
    //
    // Get the VTK data set.
    //
    vtkDataSet *in_ds = in_dr->GetDataVTK();

    if (in_ds->GetDataObjectType() != VTK_POLY_DATA)
    {
        if (!haveIssuedWarning)
        {
            avtCallback::IssueWarning("The Decimation operator can only be "
                    "applied to polygonal data.  It is not being applied.");
            haveIssuedWarning = true;
        }
        return in_dr;
    }

    vtkPolyData *pd = (vtkPolyData *) in_ds;

    vtkTriangleFilter *triangulator = vtkTriangleFilter::New();
    triangulator->SetInputData(pd);

    vtkDecimatePro *decimate = vtkDecimatePro::New();
    decimate->SetInputConnection(triangulator->GetOutputPort());
    decimate->SetTargetReduction(atts.GetTarget());
    decimate->Update();
    vtkDataSet *output = decimate->GetOutput();

    avtDataRepresentation *out_dr = new avtDataRepresentation(output,
        in_dr->GetDomain(), in_dr->GetLabel());

    decimate->Delete();
    triangulator->Delete();

    return out_dr;
}

// ****************************************************************************
// Method: avtDecimateFilter::UpdateDataObjectInfo
//
// Purpose:
//   Update the data object information.
//
// Note:       Work partially supported by DOE Grant SC0007548.
//
// Programmer: Brad Whitlock
// Creation:   Tue Mar 18 10:53:05 PDT 2014
//
// Modifications:
//
// ****************************************************************************

void
avtDecimateFilter::UpdateDataObjectInfo(void)
{
    avtPluginDataTreeIterator::UpdateDataObjectInfo();

    GetOutput()->GetInfo().GetAttributes().AddFilterMetaData("Decimate");
}

